#ifndef MIPSSIGNALINTERNAL_H
#define MIPSSIGNALINTERNAL_H
#include <signal.h>

#define UNDEF	0x0

#define MIPS__NSIG		128
#define MIPS__NSIG_BPW	(sizeof(unsigned long) * 8)
#define MIPS__NSIG_WORDS	(MIPS__NSIG / MIPS__NSIG_BPW)

typedef struct {
	XTUint32 mips_flag;
	XTUint32 local_flag;
} flag_map;

typedef struct {
	unsigned long sig[MIPS__NSIG_WORDS];
} mips_sigset_t;

typedef unsigned long mips_old_sigset_t;		/* at least 32 bits */

#define MIPS_SIGHUP			 1				/* Hangup (POSIX).  */
#define MIPS_SIGINT			 2				/* Interrupt (ANSI).  */
#define MIPS_SIGQUIT		 3				/* Quit (POSIX).  */
#define MIPS_SIGILL			 4				/* Illegal instruction (ANSI).  */
#define MIPS_SIGTRAP		 5				/* Trace trap (POSIX).  */
#define MIPS_SIGIOT			 6				/* IOT trap (4.2 BSD).  */
#define MIPS_SIGABRT		 MIPS_SIGIOT	/* Abort (ANSI).  */
#define MIPS_SIGEMT			 7
#define MIPS_SIGFPE			 8				/* Floating-point exception (ANSI).  */
#define MIPS_SIGKILL		 9				/* Kill, unblockable (POSIX).  */
#define MIPS_SIGBUS			10				/* BUS error (4.2 BSD).  */
#define MIPS_SIGSEGV		11				/* Segmentation violation (ANSI).  */
#define MIPS_SIGSYS			12
#define MIPS_SIGPIPE		13				/* Broken pipe (POSIX).  */
#define MIPS_SIGALRM		14				/* Alarm clock (POSIX).  */
#define MIPS_SIGTERM		15				/* Termination (ANSI).  */
#define MIPS_SIGUSR1		16				/* User-defined signal 1 (POSIX).  */
#define MIPS_SIGUSR2		17				/* User-defined signal 2 (POSIX).  */
#define MIPS_SIGCHLD		18				/* Child status has changed (POSIX).  */
#define MIPS_SIGCLD			MIPS_SIGCHLD	/* Same as SIGCHLD (System V).  */
#define MIPS_SIGPWR			19				/* Power failure restart (System V).  */
#define MIPS_SIGWINCH		20				/* Window size change (4.3 BSD, Sun).  */
#define MIPS_SIGURG			21				/* Urgent condition on socket (4.2 BSD).  */
#define MIPS_SIGIO			22				/* I/O now possible (4.2 BSD).  */
#define MIPS_SIGPOLL		MIPS_SIGIO		/* Pollable event occurred (System V).  */
#define MIPS_SIGSTOP		23				/* Stop, unblockable (POSIX).  */
#define MIPS_SIGTSTP		24				/* Keyboard stop (POSIX).  */
#define MIPS_SIGCONT		25				/* Continue (POSIX).  */
#define MIPS_SIGTTIN		26				/* Background read from tty (POSIX).  */
#define MIPS_SIGTTOU		27				/* Background write to tty (POSIX).  */
#define MIPS_SIGVTALRM		28				/* Virtual alarm clock (4.2 BSD).  */
#define MIPS_SIGPROF		29				/* Profiling alarm clock (4.2 BSD).  */
#define MIPS_SIGXCPU		30				/* CPU limit exceeded (4.2 BSD).  */
#define MIPS_SIGXFSZ		31				/* File size limit exceeded (4.2 BSD).  */

/* These should not be considered constants from userland.  */
#define MIPS_SIGRTMIN	32
#define MIPS_SIGRTMAX	MIPS__NSIG


static flag_map sig_table[] = {
	/* mips signum */   /* host signum */
	{	MIPS_SIGHUP,	SIGHUP		},
	{	MIPS_SIGINT,	SIGINT		},
	{	MIPS_SIGQUIT,	SIGQUIT		},
	{	MIPS_SIGILL,	SIGILL		},
	{	MIPS_SIGTRAP,	SIGTRAP		},
	{	MIPS_SIGIOT,	SIGIOT		},
	{	MIPS_SIGABRT,	SIGABRT		},
	{	MIPS_SIGEMT,	UNDEF		},	// only for MIPS
	{	MIPS_SIGFPE,	SIGFPE		},
	{	MIPS_SIGKILL,	SIGKILL		},
	{	MIPS_SIGBUS,	SIGBUS		},
	{	MIPS_SIGSEGV,	SIGSEGV		},
	{	MIPS_SIGSYS,	SIGSYS		},
	{	MIPS_SIGPIPE,	SIGPIPE		},
	{	MIPS_SIGALRM,	SIGALRM		},
	{	MIPS_SIGTERM,	SIGTERM		},
	{	MIPS_SIGUSR1,	SIGUSR1		},
	{	MIPS_SIGUSR2,	SIGUSR2		},
	{	MIPS_SIGCHLD,	SIGCHLD		},
	{	MIPS_SIGCLD,	SIGCHLD		},
	{	MIPS_SIGPWR,	SIGPWR		},
	{	MIPS_SIGWINCH,	SIGWINCH	},
	{	MIPS_SIGURG,	SIGURG		},
	{	MIPS_SIGIO,		SIGIO		},
	{	MIPS_SIGPOLL,	SIGPOLL		},
	{	MIPS_SIGSTOP,	SIGSTOP		},
	{	MIPS_SIGTSTP,	SIGTSTP		},
	{	MIPS_SIGCONT,	SIGCONT		},
	{	MIPS_SIGTTIN,	SIGTTIN		},
	{	MIPS_SIGTTOU,	SIGTTOU		},
	{	MIPS_SIGVTALRM,	SIGVTALRM	},
	{	MIPS_SIGPROF,	SIGPROF		},
	{	MIPS_SIGXCPU,	SIGXCPU		},
	{	MIPS_SIGXFSZ,	SIGXFSZ		},
	{	MIPS_SIGRTMIN,	SIGRTMIN	},
	{	UNDEF,			UNDEF		}	// table tail
};

/*
 * SA_FLAGS values:
 *
 * SA_ONSTACK indicates that a registered stack_t will be used.
 * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the
 * SA_RESTART flag to get restarting signals (which were the default long ago)
 * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
 * SA_RESETHAND clears the handler when the signal is delivered.
 * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
 * SA_NODEFER prevents the current signal from being masked in the handler.
 *
 * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
 * Unix names RESETHAND and NODEFER respectively.
 */
#define MIPS_SA_ONSTACK		0x08000000
#define MIPS_SA_RESETHAND	0x80000000
#define MIPS_SA_RESTART		0x10000000
#define MIPS_SA_SIGINFO		0x00000008
#define MIPS_SA_NODEFER		0x40000000
#define MIPS_SA_NOCLDWAIT	0x00010000
#define MIPS_SA_NOCLDSTOP	0x00000001

#define MIPS_SA_NOMASK		MIPS_SA_NODEFER
#define MIPS_SA_ONESHOT		MIPS_SA_RESETHAND
#define MIPS_SA_INTERRUPT	0x20000000	/* dummy -- ignored */

#define MIPS_SA_RESTORER	0x04000000	/* Only for o32 */

static flag_map sa_flag_table[] = {
	/* mips flag */			/* host flag */
	{	MIPS_SA_ONSTACK,	SA_ONSTACK		},
	{	MIPS_SA_RESETHAND,	SA_RESETHAND	},
	{	MIPS_SA_RESTART,	SA_RESTART		},
	{	MIPS_SA_SIGINFO,	SA_SIGINFO		},
	{	MIPS_SA_NODEFER,	SA_NODEFER		},
	{	MIPS_SA_NOCLDWAIT,	SA_NOCLDWAIT	},
	{	MIPS_SA_NOCLDSTOP,	SA_NOCLDSTOP	},
	{	MIPS_SA_NOMASK,		SA_NOMASK		},
	{	MIPS_SA_ONESHOT,	SA_ONESHOT		},
	{	MIPS_SA_INTERRUPT,	SA_INTERRUPT	},
	{	MIPS_SA_RESTORER,	UNDEF			},	//not found on local
	{	UNDEF			,	UNDEF			}	// table tail
};

/*
 * sigaltstack controls
 */
#define MIPS_SS_ONSTACK     1
#define MIPS_SS_DISABLE     2

static flag_map ss_flag_table[] = {
	/* mips flag */			/* host flag */
	{	MIPS_SS_ONSTACK,	SS_ONSTACK	},
	{	MIPS_SS_DISABLE,	SS_DISABLE	},
	{	UNDEF			,	UNDEF		}	// table tail

};


#define MIPS_MINSIGSTKSZ    2048
#define MIPS_SIGSTKSZ       8192


#define MIPS_SIG_BLOCK		1	/* for blocking signals */
#define MIPS_SIG_UNBLOCK	2	/* for unblocking signals */
#define MIPS_SIG_SETMASK	3	/* for setting the signal mask */
#define MIPS_SIG_SETMASK32	256	/* Goodie from SGI for BSD compatibility:
								set only the low 32 bit of the sigset.  */
static flag_map sb_flag_table[] = {
	/* mips flag */			/* host flag */
	{	MIPS_SIG_BLOCK,		SIG_BLOCK		},
	{	MIPS_SIG_UNBLOCK,	SIG_UNBLOCK		},
	{	MIPS_SIG_SETMASK,	SIG_SETMASK		},
	{	MIPS_SIG_SETMASK32,	SIG_SETMASK		},	// only for MIPS
	{	UNDEF			,	UNDEF			}	// table tail
};


/* Type of a signal handler.  */
typedef void (*mips__sighandler_t)(int);
typedef void (*mips_sa_sigaction) (int, siginfo_t *, void *); //FIXME: siginfo_t should be change to mips's

typedef struct {
	mips__sighandler_t mips_fn;
	__sighandler_t	local_fn;
} fn_map;


/* Fake signal functions */
#define MIPS_FNTBL_SZ	3
#define MIPS_SIG_DFL	((mips__sighandler_t)0)		/* default signal handling */
#define MIPS_SIG_IGN	((mips__sighandler_t)1)		/* ignore signal */
#define MIPS_SIG_ERR	((mips__sighandler_t)-1)	/* error return from signal */

static fn_map sh_fn_table[MIPS_FNTBL_SZ] = {
	/* mips flag */   /* host flag */
	{	MIPS_SIG_DFL,	SIG_DFL	},
	{	MIPS_SIG_IGN,	SIG_IGN	},
	{	MIPS_SIG_ERR,	SIG_ERR	}
};

struct mips_sigaction {
	unsigned int		sa_flags;
	mips__sighandler_t	sa_hdler;	//if named as sa_handler, GCC reports an error!! Why?
	mips_sigset_t		sa_mask;
};

struct mips_k_sigaction {
	struct mips_sigaction sa;
};

/* IRIX compatible stack_t  */
typedef struct mips_sigaltstack {
	void	*ss_sp;
	size_t	ss_size;
	int		ss_flags;
} mips_stack_t;

#endif
